import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getUserSelector } from '../store/selectors/selectUserData';
import { setUserData } from '../store/slices/userSlice';
import authServices from '../services/authServices';
import Snipper from '../shared/ui/Spinner/Spinner';
import { routes } from '../constants/routes';
import AuthProviderContext from '../context/AuthProviderContext';
import { IRoute } from '../types/routeType';
import { PERM } from '../constants/permissions';
import { notifyError } from '../utils/toastify';
import './Snipper.scss';

/**
 * @typedef { Object } IAuthProvider - Интерфейс для компонента AuthProvider.
 * @property { ReactNode } children - Дочерние элементы, передаваемые в AuthProvider.
 */
interface IAuthProvider {
    children: React.ReactNode,
}

/**
 * @function AuthProvider - В зависимости от того авторизован ли пользователь
 *  отображает либо дочерние компоненты, либо сниппер загрузки.
 * 
 * @param { React.ReactNode } children - Дочерние компоненты. 
 * @returns { React.ReactNode } - Возвращает либо переданные дочерние компоненты, либо сниппер загрузки.
 */
const AuthProvider: React.FC<IAuthProvider> = ({ children } ): React.ReactNode => {

    const userData = useSelector(getUserSelector);

    const dispatch = useDispatch();

    const [routesState, setRoutesState] = React.useState([]);

    /**
     * Асинхронно получает данные пользователя и сохраняет их в хранилище redux.
     * 
     * @async
     * @function getUserData
     * @returns { void }
     */
    const getUserData = async () => {

        try {
            const response = await authServices.getProfile();

            const availableRoutes = routes.filter((route: IRoute) =>
                response.permissions.some((perm: PERM) => route.allowed.includes(perm)))
            dispatch(setUserData(response));

            setRoutesState(availableRoutes);

        } catch (err) {
            console.error(err);
        }
    };

    React.useEffect(
        () => {
            getUserData();
        }, []
    );

    const memoValue = React.useMemo(() => ({ availableRoutes: routesState }), [routesState]);

    return (
        <AuthProviderContext.Provider value={ memoValue }>
            {userData ? children : <div className='snipper'><Snipper /></div>}
        </AuthProviderContext.Provider>
    );
};

AuthProvider.displayName = "AuthProvider";

export default AuthProvider;